package com.nwpu.main;

import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.util.Arrays;
import java.util.Scanner;

/**
 * RMIClient
 *
 * @author 龙虹宇
 * @version 1.0
 * @date 2023/11/11
 */
public class RMIClient {
    // 默认port
    private static int PORT = 1099;
    // 默认ip
    private static String IP = "127.0.0.1";
    // RMIRegister仓库
    private static Registry registry;
    // MethodSet方法类
    private static MethodSet methodSet;

    private static Scanner scanner = new Scanner(System.in);

    public static void main(String[] args) throws RemoteException {
        // args = new String[] {"a" ,"b", "c"};
        // args = new String[] {"a" ,"b"};
        // args = new String[] {"localhost" ,"1099" ,"a"};
        // args = new String[] {"localhost" ,"1099" ,"register", "zhangsa", "1111"};
        // args = new String[] {"localhost" ,"1099" ,"register", "wangwu", "1111"};
        // args = new String[] {"localhost" ,"1099" ,"add", "wangwu", "1111", "zhangsa", "2023-11-01" ,"17:00:00", "2023-11-01" ,"18:00:00", "aaa的会议"};
        // 初始化ip和port
        init(args);
        // 截取指令参数并执行一次指令
        String[] insArgs = Arrays.copyOfRange(args, 2, args.length);
        processIns(insArgs);
        // 第一次默认输出指令菜单
        System.out.println(methodSet.help());

        // 循环
        while (true) {
            System.out.println("请输入指令：");
            String input = scanner.nextLine();
            if (input == null || "".equals(input.trim())) continue;
            processIns(input.split(" "));
        }
    }

    /**
     * 判断参数个数是否合法
     *
     * @param args
     * @param len
     * @return  true：合法
     *          false：不合法
     */
    public static boolean paramLegal(String args[], int len) {
        if (args.length != len) {
            System.out.println("info：参数个数不合法");
            return false;
        }
        return true;
    }

    /**
     * 本地处理指令
     *
     * @param args
     * @throws RemoteException
     */
    public static void processIns(String[] args) throws RemoteException {
        switch (args[0]) {
            case "register":
                proRegister(args);
                break;
            case "add":
                proAdd(args);
                break;
            case "query":
                proQuery(args);
                break;
            case "delete":
                proDelete(args);
                break;
            case "clear":
                proClear(args);
                break;
            case "help":
                proHelp(args);
                break;
            case "quit":
                proQuit(args);
                break;
            default:
                System.out.println("info：指令错误");
                break;
        }
    }

    /**
     * 处理删除所有会议方法响应
     *
     * @param args
     * @throws RemoteException
     */
    private static void proClear(String[] args) throws RemoteException {
        // 判断参数个数是否正确
        if (!paramLegal(args, 3)) return;
        // 调用远程方法
        String res = methodSet.clear(args[1], args[2]);
        switch (res) {
            case "no_user":
                System.out.println("error：当前不存在用户");
                break;
            case "no_meeting":
                System.out.println("error：当前不存在会议");
                break;
            case "wrong":
                System.out.println("error：用户名或密码错误");
                break;
            case "none":
                System.out.println("info：未查询到相关会议");
                break;
            case "success":
                System.out.println("info：" + args[1] + "先生/女士，" + "已为您删除所有会议");
                break;
            default:
                System.out.println("error：删除会议失败");
                break;
        }
    }

    /**
     * 处理删除会议方法响应
     *
     * @param args
     * @throws RemoteException
     */
    private static void proDelete(String[] args) throws RemoteException {
        // 判断参数个数是否正确
        if (!paramLegal(args, 4)) return;
        // 调用远程方法
        String res = methodSet.delete(args[1], args[2], args[3]);
        switch (res) {
            case "no_user":
                System.out.println("error：当前不存在用户");
                break;
            case "no_meeting":
                System.out.println("error：当前不存在会议");
                break;
            case "wrong":
                System.out.println("error：用户名或密码错误");
                break;
            case "wrong_id":
                System.out.println("error：会议id错误");
                break;
            case "none":
                System.out.println("info：未查到相关会议");
                break;
            case "success":
                System.out.println("info：会议删除成功，id：" + args[3]);
                break;
            default:
                System.out.println("error：删除会议失败");
                break;
        }
    }

    /**
     * 处理查询会议方法响应
     *
     * @param args
     * @throws RemoteException
     */
    private static void proQuery(String[] args) throws RemoteException {
        // 判断参数个数是否正确
        if (!paramLegal(args, 7)) return;
        // 调用远程方法
        String res = methodSet.query(args[1], args[2], args[3] + " " + args[4], args[5] + " " + args[6]);
        switch (res) {
            case "no_user":
                System.out.println("error：当前没有用户注册");
                break;
            case "wrong":
                System.out.println("error：用户名或密码错误");
                break;
            case "no_meeting":
                System.out.println("error：当前没有添加会议");
                break;
            case "wrong_date":
                System.out.println("error：时间格式错误");
                break;
            case "wrong_date_value":
                System.out.println("error：时间数值错误");
                break;
            case "none":
                System.out.println("info：未查询到相关会议");
                break;
            default:
                if (res.startsWith("==Meetings==")) {
                    System.out.println(res);
                } else {
                    System.out.println("error：查询失败");
                }
                break;
        }
    }

    /**
     * 处理添加会议方法响应
     *
     * @param args
     * @throws RemoteException
     */
    private static void proAdd(String[] args) throws RemoteException {
        // 判断参数个数是否正确
        if (!paramLegal(args, 9)) return;
        // 调用远程方法
        String res = methodSet.add(args[1], args[2], args[3], args[4] + " " + args[5], args[6] + " " + args[7], args[8]);
        switch (res) {
            case "success":
                System.out.println("info：会议：" + args[8] + "已成功创建");
                break;
            case "less":
                System.out.println("info：当前注册用户不足两人");
                break;
            case "same_name":
                System.out.println("error：创建者和参会者相同");
                break;
            case "wrong":
                System.out.println("error：用户名或密码或参会者用户名错误");
                break;
            case "wrong_date":
                System.out.println("error：时间格式错误");
                break;
            case "wrong_date_value":
                System.out.println("error：时间数值错误");
                break;
            case "conflict":
                System.out.println("error：会议时间冲突");
                break;
            default:
                System.out.println("error：添加会议失败");
                break;
        }
    }

    /**
     * 处理退出方法
     */
    public static void proQuit(String[] args) {
        // 判断参数个数是否正确
        if (!paramLegal(args, 1)) return;
        System.out.println("info：退出服务");
        System.exit(0);
    }

    /**
     * 处理帮助方法响应
     *
     * @param args
     * @throws RemoteException
     */
    public static void proHelp(String[] args) throws RemoteException {
        // 判断参数个数是否正确
        if (!paramLegal(args, 1)) return;
        // 调用远程方法
        String res = methodSet.help();
        System.out.println(res);
    }

    /**
     * 处理注册方法响应
     *
     * @param args
     * @throws RemoteException
     */
    public static void proRegister(String[] args) throws RemoteException {
        // 判断参数个数是否正确
        if (!paramLegal(args, 3)) return;
        // 调用远程方法
        String res = methodSet.register(args[1], args[2]);
        switch (res) {
            case "s":
                System.out.println("info：欢迎您：" + args[1] + "先生/女士");
            break;
            case "f":
                System.out.println("error：用户名已存在");
            break;
        }
    }

    /**
     * 输出错误信息
     *
     * @param info
     */
    public static void wrongInfo(String info) {
        System.out.println(info);
        System.exit(0);
    }

    /**
     * 初始化静态变量
     */
    public static void init(String[] args) {
        // 判断启动参数是否合法
        if (args.length < 3) wrongInfo("error：指令错误");

        try {
            // 获取端口和ip
            IP = args[0];
            PORT = Integer.parseInt(args[1]);
            // 定向获取RMIRegister
            registry = LocateRegistry.getRegistry(IP, PORT);
            // 判断port和ip是否合法
            if (registry.list().length == 0) wrongInfo("error：无法连接对应ip及port");
            // 检索stub
            methodSet = (MethodSet)registry.lookup("methodSet");

        } catch (RemoteException | NotBoundException e) {
            e.printStackTrace();
        } catch (NumberFormatException e) {
            wrongInfo("error：port不合法");
        }
    }
}
